/*------------------------------------------------------------------------------
 * Copyright 2012 NCR Corporation
 *------------------------------------------------------------------------------
 * All revision information is updated automatically from source code control
 * change records - please do not manually edit.
 *------------------------------------------------------------------------------
 *
 * $LastChangedRevision:: 2026                                     $
 * $LastChangedBy:: rb250096                                       $
 * $LastChangedDate:: 2012-04-07 18:34:30 -0400 (Sat, 07 Apr 2012) $
 */

package com.ncr.nep.dashboardcore.rest.client;

import java.util.logging.Logger;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.ncr.nep.dashboardcore.utils.client.StringUtil;

/**
 * Callback that handles a text response.  Additionally, it attempts to
 * handle various types of errors from the server such as JSON error objects.
 *
 * @author rb250096
 * @version $Revision: 2026 $
 */
public abstract class TextCallback implements RequestCallback {

    //--------------------------------------------------------------------------
    //
    //  Fields
    //
    //--------------------------------------------------------------------------

    /**
     * Constant used for status code in {@link #onFailure(Throwable, int)}
     * invocation where no Response is available due to errors like an
     * unknown host or no network connection.
     */
    public static final int NO_RESPONSE = -1;

    /**
     * Query parameter in host page URL indicating that response bodies should
     * be logged for debugging purposes.
     */
    public static final String LOG_REPSONSES_QUERY_PARAM = "logResponses";

    /**
     * Logging instance.
     */
    private static Logger log = Logger.getLogger("TextCallback");

    /**
     * The request object sent to the server.
     */
    protected Request request;

    /**
     * The response object received from the server.
     */
    protected Response response;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    /**
     * Indicates that response logging is enabled.
     *
     * @return True if response bodies should be logged.
     */
    public boolean isLogResponsesEnabled() {
        String enabledString =
                Window.Location.getParameter(LOG_REPSONSES_QUERY_PARAM);
        return enabledString != null &&
                enabledString.toLowerCase().equals("true");
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Callback method invoked when the remote request associated with the
     * callback returns successfully.
     *
     * @param result The text result from the response.
     */
    public abstract void onSuccess(String result);

    /**
     * Callback method invoked when the remote request associated with the
     * callback fails due to an error.
     *
     * @param throwable Throwable with details on the error that occurred.
     * @param statusCode The HTTP status code returned in the server response
     *                   indicating the category of error that occurred.
     */
    public abstract void onFailure(Throwable throwable, int statusCode);

    @Override
    public void onResponseReceived(Request request, Response response) {
        this.request = request;
        this.response = response;

        String contentType = response.getHeader("Content-Type");

        if(this.isLogResponsesEnabled()) {
            log.info(StringUtil.substitute(
                    "Received response. SC: {0} MIME-Type: {1} Body:\n",
                    response.getStatusCode(), contentType) +
                    response.getText());
        }

        if(response.getStatusCode() == Response.SC_OK) {
            this.onSuccess(response.getText());
        }
        else if(contentType != null) {
            if(contentType.equals("text/plain")) {
                this.onFailure(new PlainTextException(response.getText()),
                        response.getStatusCode());
            }
            else if(contentType.equals("application/json")) {
                this.onFailure(new JSONException(response.getText()),
                        response.getStatusCode());
            }
            else {
                this.onFailure(new RuntimeException("An error occurred " +
                        "in the request. Response: " + response.getText()),
                        response.getStatusCode());
            }
        }
        else {
            this.onFailure(new RuntimeException("An error occured " +
                    "in the request."), response.getStatusCode());
        }
    }

    @Override
    public void onError(Request request, Throwable throwable) {
        this.request = request;
        this.onFailure(throwable, NO_RESPONSE);
    }
}
